package com.yanqu.xiuxian.crosssystem.manger.elementalbonds.logic;

import com.yanqu.xiuxian.config.elementalbonds.ElementalBondsConfigMgr;
import com.yanqu.xiuxian.config.elementalbonds.ElementalBondsHardLevelConfig;
import com.yanqu.xiuxian.config.elementalbonds.ElementalBondsParam;
import com.yanqu.xiuxian.config.elementalbonds.enums.ElementalBondsBlockBigType;
import com.yanqu.xiuxian.config.elementalbonds.enums.ElementalBondsColorType;
import com.yanqu.xiuxian.config.elementalbonds.enums.ElementalBondsOperateType;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.CrossElementalBondsMgr;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.data.*;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.entity.ElementalBondsBlock;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.enums.ElementalBondsSkillType;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.param.ElementalBondsAiMoveParam;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.param.ElementalBondsCardParam;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.param.ElementalBondsMoveParam;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.param.ElementalBondsSkillParam;
import com.yanqu.xiuxian.server.protocol.GameErrorCode;
import com.yanqu.xiuxian.utils.RandomHelper;

import java.util.*;

public class ElementalBondsAiLogic {

    public static int aiOperate(CrossElementalBondsMgr crossElementalBondsMgr, ElementalBondsRoomData elementalBondsRoomData,
                                ElementalBondsMatchData realPlayer, ElementalBondsPlayerData aiPlayer) {

        // 拿AI难度
        List<Integer> hardWeightList = ElementalBondsParam.getInstance().getAiHardList().get(0);
        int rankId = ElementalBondsConfigMgr.getInstance().getScoreConfig(realPlayer.getScore(), realPlayer.isNovice()).getTitle();
        for (List<Integer> list : ElementalBondsParam.getInstance().getAiHardList()) {
            if (list.get(0) <= rankId && rankId <= list.get(1)) {
                hardWeightList = new ArrayList<>(list);
                hardWeightList.remove(0);
                hardWeightList.remove(0);
            }
        }
        int hardLevel = RandomHelper.getRandomIndexByWeight(hardWeightList) + 1;
        ElementalBondsHardLevelConfig elementalBondsHardLevelConfig = ElementalBondsConfigMgr.getInstance().getHardLevelConfigMap().get(hardLevel);

        // -------------------- 准备结果 -----------------------

        boolean canUseCard = false;
        ElementalBondsCardData elementalBondsCardData = aiPlayer.getElementalBondsCardData();
        if (elementalBondsCardData.getCardMp() >= elementalBondsCardData.getCardMaxMp()) {
            canUseCard = true;
        }

        int side = elementalBondsRoomData.getPlayer1() == aiPlayer ? 1 : 2;
        ElementalBondsAiMoveParam bestAiMove = getBestAiMove(elementalBondsRoomData.getGameData(), side, aiPlayer, elementalBondsHardLevelConfig);

        // -------------------- 选一种好用的操作 -----------------------

        if (bestAiMove == null) {
            return GameErrorCode.E_ELEMENTAL_BONDS_PARAM_ERROR;
        }

        // 默认移动
        ElementalBondsOperateType elementalBondsOperateType = ElementalBondsOperateType.MOVE;
        int weight = bestAiMove.getWeight(elementalBondsHardLevelConfig);

        // 看看卡片
        if (canUseCard && elementalBondsHardLevelConfig.getCardWeight() > weight) {
            elementalBondsOperateType = ElementalBondsOperateType.USE_CARD;
            weight = elementalBondsHardLevelConfig.getCardWeight();
        }

        // 看看盘面技能
        int useSkillId = 0;
        int skillX = 0;
        int skillY = 0;
        if (weight < elementalBondsHardLevelConfig.getSkillWeight() || elementalBondsRoomData.getRound() >= 5) { // 有权重限制 || 第五回合强制判断
            for (ElementalBondsSkillData elementalBondsSkillData : aiPlayer.getElementalBondsSkillDataList()) {

                if (elementalBondsSkillData.getSkillId() == ElementalBondsSkillType.SKILL_1001.getType()) {
                    // 有次数 && 第2回合及以后 && 50%概率触发
                    if (elementalBondsSkillData.getTimes() > 0 && elementalBondsRoomData.getRound() >= 2 && new Random().nextInt(1000) < 500) {
                        weight = elementalBondsHardLevelConfig.getSkillWeight();
                        elementalBondsOperateType = ElementalBondsOperateType.USE_SKILL;
                        useSkillId = elementalBondsSkillData.getSkillId();
                        break;
                    }
                }

                if (elementalBondsSkillData.getSkillId() == ElementalBondsSkillType.SKILL_1002.getType()) {
                    // 有次数 && 第3回合及以后 && 排序后选最优的
                    if (elementalBondsSkillData.getTimes() > 0 && elementalBondsRoomData.getRound() >= 3) {
                        List<ElementalBondsBlock> allElementalBondsBlockList = new ArrayList<>();
                        for (List<ElementalBondsBlock> blockList : elementalBondsRoomData.getGameData().getBlockList()) {
                            allElementalBondsBlockList.addAll(blockList);
                        }
                        int color = elementalBondsRoomData.getTurnPlayer() == 1 ? ElementalBondsColorType.RED.getType() : ElementalBondsColorType.BLUE.getType();
                        allElementalBondsBlockList.sort((o1, o2) -> Integer.compare(
                                getBlockSortScore(o2, color),
                                getBlockSortScore(o1, color)
                        ));
                        ElementalBondsBlock chooseElementalBondsBlock = allElementalBondsBlockList.get(0);
                        int sortScore = getBlockSortScore(chooseElementalBondsBlock, color);
                        // 是炸弹 || 操作后满蓝
                        if (sortScore > 1000 || sortScore > 100 && aiPlayer.getElementalBondsCardData().getCardMp() + 1 == aiPlayer.getElementalBondsCardData().getCardMaxMp()) {
                            weight = elementalBondsHardLevelConfig.getSkillWeight();
                            elementalBondsOperateType = ElementalBondsOperateType.USE_SKILL;
                            useSkillId = elementalBondsSkillData.getSkillId();
                            skillX = chooseElementalBondsBlock.getX();
                            skillY = chooseElementalBondsBlock.getY();
                            break;
                        }
                    }
                }
            }
        }

        // --------------------- 执行操作 ----------------------

        // 【使用盘面技能】
        if (elementalBondsOperateType == ElementalBondsOperateType.USE_SKILL) {
            ElementalBondsSkillParam elementalBondsSkillParam = new ElementalBondsSkillParam(useSkillId, skillX, skillY);
            return crossElementalBondsMgr.operateNpcUseSkill(elementalBondsRoomData, elementalBondsSkillParam, aiPlayer);
        }

        // 【使用卡片】
        if (elementalBondsOperateType == ElementalBondsOperateType.USE_CARD) {
            ElementalBondsCardParam elementalBondsCardParam = new ElementalBondsCardParam(elementalBondsCardData.getCardId());
            // 暂时只能操作无参数卡片
            return crossElementalBondsMgr.operateNpcUseCard(elementalBondsRoomData, elementalBondsCardParam, aiPlayer);
        }

        // 【移动】
        return crossElementalBondsMgr.operateNpcMove(elementalBondsRoomData, bestAiMove.getElementalBondsMoveParam(), aiPlayer);
    }


    /**
     * @param elementalBondsPlayerData 可以null
     */
    public static ElementalBondsAiMoveParam getBestAiMove(ElementalBondsGameData elementalBondsGameData, int side,
                                                          ElementalBondsPlayerData elementalBondsPlayerData, ElementalBondsHardLevelConfig elementalBondsHardLevelConfig) {
        ElementalBondsAiMoveParam bestParam = null;
        List<List<ElementalBondsBlock>> blockList = elementalBondsGameData.clone().getBlockList();

        // 先检查组合炸弹
        for (int y = 0; y < blockList.size(); y++) {
            for (int x = 0; x < blockList.get(y).size(); x++) {
                ElementalBondsBlock fromElementalBondsBlock = blockList.get(y).get(x);
                if (ElementalBondsBlockLogic.combBombPart(fromElementalBondsBlock)) {
                    if (ElementalBondsBlockLogic.exist(blockList, x + 1, y) && ElementalBondsBlockLogic.combBombPart(blockList.get(y).get(x + 1))) {
                        ElementalBondsAiMoveParam elementalBondsAiMoveParam = createElementalBondsAiMoveParam(blockList, x, y, x + 1, y, side, elementalBondsPlayerData);
                        if (bestParam == null || elementalBondsAiMoveParam.getWeight(elementalBondsHardLevelConfig) > bestParam.getWeight(elementalBondsHardLevelConfig)) {
                            bestParam = elementalBondsAiMoveParam;
                        }
                    }
                    if (ElementalBondsBlockLogic.exist(blockList, x, y + 1) && ElementalBondsBlockLogic.combBombPart(blockList.get(y + 1).get(x))) {
                        ElementalBondsAiMoveParam elementalBondsAiMoveParam = createElementalBondsAiMoveParam(blockList, x, y, x, y + 1, side, elementalBondsPlayerData);
                        if (bestParam == null || elementalBondsAiMoveParam.getWeight(elementalBondsHardLevelConfig) > bestParam.getWeight(elementalBondsHardLevelConfig)) {
                            bestParam = elementalBondsAiMoveParam;
                        }
                    }
                }
            }
        }

        // 遍历每个方块尝试交换
        for (int y = 0; y < blockList.size(); y++) {
            for (int x = 0; x < blockList.get(y).size(); x++) {

                // 跟右边交换
                int x2 = x + 1;
                int y2 = y;
                if (ElementalBondsBlockLogic.exist(blockList, x2, y2)) {
                    ElementalBondsBlockLogic.exchange(blockList, x, y, x2, y2, null);
                    if (ElementalBondsEliminateLogic.canSameColorEliminate(blockList, blockList.get(y).get(x)) || ElementalBondsEliminateLogic.canSameColorEliminate(blockList, blockList.get(y2).get(x2))) {
                        ElementalBondsAiMoveParam elementalBondsAiMoveParam = createElementalBondsAiMoveParam(blockList, x, y, x2, y2, side, elementalBondsPlayerData);
                        if (bestParam == null || elementalBondsAiMoveParam.getWeight(elementalBondsHardLevelConfig) > bestParam.getWeight(elementalBondsHardLevelConfig)) {
                            bestParam = elementalBondsAiMoveParam;
                        }
                    }
                    ElementalBondsBlockLogic.exchange(blockList, x, y, x2, y2, null);
                }

                // 跟上边交换
                x2 = x;
                y2 = y + 1;
                if (ElementalBondsBlockLogic.exist(blockList, x2, y2)) {
                    ElementalBondsBlockLogic.exchange(blockList, x, y, x2, y2, null);
                    if (ElementalBondsEliminateLogic.canSameColorEliminate(blockList, blockList.get(y).get(x)) || ElementalBondsEliminateLogic.canSameColorEliminate(blockList, blockList.get(y2).get(x2))) {
                        ElementalBondsAiMoveParam elementalBondsAiMoveParam = createElementalBondsAiMoveParam(blockList, x, y, x2, y2, side, elementalBondsPlayerData);
                        if (bestParam == null || elementalBondsAiMoveParam.getWeight(elementalBondsHardLevelConfig) > bestParam.getWeight(elementalBondsHardLevelConfig)) {
                            bestParam = elementalBondsAiMoveParam;
                        }
                    }
                    ElementalBondsBlockLogic.exchange(blockList, x, y, x2, y2, null);
                }

            }
        }

        return bestParam;
    }

    /**
     * @param elementalBondsPlayerData 可以null
     */
    private static ElementalBondsAiMoveParam createElementalBondsAiMoveParam(List<List<ElementalBondsBlock>> blockList, int x1, int y1, int x2, int y2,
                                                                             int side, ElementalBondsPlayerData elementalBondsPlayerData) {
        ElementalBondsAiMoveParam elementalBondsAiMoveParam = new ElementalBondsAiMoveParam();
        elementalBondsAiMoveParam.setElementalBondsMoveParam(new ElementalBondsMoveParam(x1, y1, x2, y2));

        int blueColor = side == 1 ? ElementalBondsColorType.RED.getType() : ElementalBondsColorType.BLUE.getType();
        int redColor = side == 1 ? ElementalBondsColorType.BLUE.getType() : ElementalBondsColorType.RED.getType();
        int addMp = 0;

        List<ElementalBondsBlock> elementalBondsBlockList = new ArrayList<>();
        elementalBondsBlockList.add(blockList.get(y1).get(x1));
        elementalBondsBlockList.add(blockList.get(y2).get(x2));

        for (ElementalBondsBlock elementalBondsBlock : elementalBondsBlockList) {
            int color = elementalBondsBlock.getColor();
            Set<ElementalBondsBlock> xSet = new HashSet<>();
            Set<ElementalBondsBlock> ySet = new HashSet<>();
            xSet.add(elementalBondsBlock);
            ySet.add(elementalBondsBlock);

            int tmpX = elementalBondsBlock.getX() + 1;
            int tmpY = elementalBondsBlock.getY();
            if (ElementalBondsBlockLogic.exist(blockList, tmpX, tmpY) && blockList.get(tmpY).get(tmpX).getColor() == color) {
                xSet.add(blockList.get(tmpY).get(tmpX));
                tmpX++;
                if (ElementalBondsBlockLogic.exist(blockList, tmpX, tmpY) && blockList.get(tmpY).get(tmpX).getColor() == color) {
                    xSet.add(blockList.get(tmpY).get(tmpX));
                }
            }
            tmpX = elementalBondsBlock.getX() - 1;
            tmpY = elementalBondsBlock.getY();
            if (ElementalBondsBlockLogic.exist(blockList, tmpX, tmpY) && blockList.get(tmpY).get(tmpX).getColor() == color) {
                xSet.add(blockList.get(tmpY).get(tmpX));
                tmpX--;
                if (ElementalBondsBlockLogic.exist(blockList, tmpX, tmpY) && blockList.get(tmpY).get(tmpX).getColor() == color) {
                    xSet.add(blockList.get(tmpY).get(tmpX));
                }
            }
            tmpX = elementalBondsBlock.getX();
            tmpY = elementalBondsBlock.getY() + 1;
            if (ElementalBondsBlockLogic.exist(blockList, tmpX, tmpY) && blockList.get(tmpY).get(tmpX).getColor() == color) {
                ySet.add(blockList.get(tmpY).get(tmpX));
                tmpY++;
                if (ElementalBondsBlockLogic.exist(blockList, tmpX, tmpY) && blockList.get(tmpY).get(tmpX).getColor() == color) {
                    ySet.add(blockList.get(tmpY).get(tmpX));
                }
            }
            tmpX = elementalBondsBlock.getX();
            tmpY = elementalBondsBlock.getY() - 1;
            if (ElementalBondsBlockLogic.exist(blockList, tmpX, tmpY) && blockList.get(tmpY).get(tmpX).getColor() == color) {
                ySet.add(blockList.get(tmpY).get(tmpX));
                tmpY--;
                if (ElementalBondsBlockLogic.exist(blockList, tmpX, tmpY) && blockList.get(tmpY).get(tmpX).getColor() == color) {
                    ySet.add(blockList.get(tmpY).get(tmpX));
                }
            }

            if (xSet.size() >= 3 && ySet.size() >= 3 || xSet.size() >= 4 || ySet.size() >= 4) {
                elementalBondsAiMoveParam.setCreateBomb(true); // 【修改】
            }
            if (xSet.size() >= 3) {
                for (ElementalBondsBlock tmp : xSet) {
                    if (tmp.getElementalBondsBlockType().getBigType() == ElementalBondsBlockBigType.NORMAL_BOMB ||
                            tmp.getElementalBondsBlockType().getBigType() == ElementalBondsBlockBigType.SPECIAL_BOMB ||
                            !tmp.getElementalBondsBlockEffectList().isEmpty()) {
                        elementalBondsAiMoveParam.setBoom(true); // 【修改】
                        break;
                    }
                }
            }
            if (ySet.size() >= 3 && !elementalBondsAiMoveParam.isBoom()) {
                for (ElementalBondsBlock tmp : ySet) {
                    if (tmp.getElementalBondsBlockType().getBigType() == ElementalBondsBlockBigType.NORMAL_BOMB ||
                            tmp.getElementalBondsBlockType().getBigType() == ElementalBondsBlockBigType.SPECIAL_BOMB ||
                            !tmp.getElementalBondsBlockEffectList().isEmpty()) {
                        elementalBondsAiMoveParam.setBoom(true); // 【修改】
                        break;
                    }
                }
            }
            if (xSet.size() >= 3 && ySet.size() >= 3) {
                elementalBondsAiMoveParam.setDoubleEliminate(true); // 【修改】
            }
            if (elementalBondsBlock.getColor() == blueColor) {
                addMp = addMp + (xSet.size() >= 3 ? xSet.size() : 0) + (ySet.size() >= 3 ? ySet.size() : 0);
                elementalBondsAiMoveParam.setAddMp(true); // 【修改】
            }
            if (elementalBondsBlock.getColor() == redColor) {
                elementalBondsAiMoveParam.setSubMp(true); // 【修改】
            }
        }

        // 【判断组合炸弹】
        if (ElementalBondsBlockLogic.combBombPart(elementalBondsBlockList.get(0)) && ElementalBondsBlockLogic.combBombPart(elementalBondsBlockList.get(1))) {
            elementalBondsAiMoveParam.setCombBoom(true); // 【修改】
        }

        // 【判断蓝满了】
        if (elementalBondsPlayerData != null) {
            ElementalBondsCardData elementalBondsCardData = elementalBondsPlayerData.getElementalBondsCardData();
            if (elementalBondsPlayerData.getStep() == 1 || elementalBondsAiMoveParam.isCreateBomb()) { // 还有步数
                if (addMp + elementalBondsCardData.getCardMp() >= elementalBondsCardData.getCardMaxMp()) {
                    elementalBondsAiMoveParam.setHasStepMpFull(true);
                }
            }
        }

        return elementalBondsAiMoveParam;
    }

    private static int getBlockSortScore(ElementalBondsBlock elementalBondsBlock, int color) {
        int score = 0;

        // 类型
        if (elementalBondsBlock.getElementalBondsBlockType().getBigType() == ElementalBondsBlockBigType.NORMAL_BOMB
                || elementalBondsBlock.getElementalBondsBlockType().getBigType() == ElementalBondsBlockBigType.SPECIAL_BOMB) {
            score += 1000;
        } else if (elementalBondsBlock.getElementalBondsBlockType().getBigType() == ElementalBondsBlockBigType.SPECIAL) {
            score += 50;
        }

        // 颜色
        if (elementalBondsBlock.getColor() == color) {
            score += 100;
        }

        // 位置（越下面越好）
        score += (10 - elementalBondsBlock.getY());

        return score;
    }

}
